package com.fingard.dsp.bank.directbank.chanpay01;

import java.net.URL;
import java.util.Date;
import java.util.HashMap;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.directbank.chanpay01.chanpay01Util.CjSignHelper;
import com.fingard.dsp.bank.directbank.chanpay01.chanpay01Util.HttpPostBodyMethod;
import com.fingard.dsp.bank.directbank.chanpay01.chanpay01Util.U;
import com.fingard.dsp.bank.directbank.chanpay01.chanpay01Util.Util;
import com.fingard.dsp.bank.directbank.chanpay01.chanpay01Util.CjSignHelper.VerifyResult;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.io.FileHelper;
import com.fingard.text.StringHelper;
import com.fingard.util.DateHelper;
import com.fingard.xml.XmlTextReader;

public class ChanPay01SinglePay extends ChanPay01Base implements ISinglePay{

	@Override
	public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
		//返回ATS的对象
		RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
		RetAtsSglDetail tmpRetDetail;
		tmpRetDetail = d_190802(p_req1908);
		
		if(tmpRetDetail.respCode.equals("-1") && StringHelper.isNullOrEmpty(tmpRetDetail.reqSeqID)){
			tmpRetDetail.reqSeqID = p_req1908.singleDetail.askNumber;
		}
		retAts.writeRetDetail(tmpRetDetail);
		return retAts;
	}

	@Override
	public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
		return null;
	}

	//190802对外支付
		private RetAtsSglDetail d_190802(ReqSingle p_req1908) throws Exception{
			RetAtsSglDetail retDetail = new RetAtsSglDetail();
			try {
				ActSetItem actItem = getBankConfig().getActSetItem(p_req1908.singleDetail.payAct, "");
				if (actItem == null || !FileHelper.existFile(actItem.ownKeyStorePath)
						|| !FileHelper.existFile(actItem.oppCertFilePath)) {
					if (actItem == null) {
						throw new Exception("未找到账号" + p_req1908.singleDetail.payAct + "的批量商户配置节点");
					} else {
						throw new Exception("账号" + p_req1908.singleDetail.payAct + "的证书文件不存在");
					}
				}
				Document doc = DocumentHelper.createDocument();
				Element msgEl = doc.addElement("MESSAGE");

				Element infoEl = msgEl.addElement("INFO");
				infoEl.addElement("TRX_CODE").setText("G10002");
				infoEl.addElement("VERSION").setText("01");
				infoEl.addElement("MERCHANT_ID").setText(actItem.merchantId);
				infoEl.addElement("REQ_SN").setText(p_req1908.singleDetail.askNumber);
				infoEl.addElement("TIMESTAMP").setText( U.getCurrentTimestamp());
				infoEl.addElement("SIGNED_MSG").setText("");
				
				Element bodyEl = msgEl.addElement("BODY");
				String BUSINESS_CODE = this.getBankConfig().getMapAdvanceValue
						("BUSINESS_CODE_1908", "srcCode", "desCode",p_req1908.singleDetail.purpose);
				//ATS传入的用途必须是 信息服务费
				bodyEl.addElement("BUSINESS_CODE").setText(BUSINESS_CODE);
				bodyEl.addElement("CORP_ACCT_NO").setText(actItem.merchantId);
				System.out.println(p_req1908.reqHeader.commandCode);
				String PRODUCT_CODE = this.getBankConfig().getMapAdvanceValue
						("PRODUCT_CODE_1908", "srcCode", "desCode",p_req1908.reqHeader.commandCode);//传入线路代码 获得产品编码
				bodyEl.addElement("PRODUCT_CODE").setText(PRODUCT_CODE);
				if("1".equals(p_req1908.singleDetail.isPrivate)){
					//对私 0
					bodyEl.addElement("ACCOUNT_PROP").setText("0");
				}
				else{
					//对公
					bodyEl.addElement("ACCOUNT_PROP").setText("1");
				}
				bodyEl.addElement("SUB_MERCHANT_ID").setText(Format.DateTime14Format.format(p_req1908.singleDetail.getPayDateTime()));
				
				bodyEl.addElement("BANK_GENERAL_NAME").setText(p_req1908.singleDetail.payBankName);
				if(p_req1908.singleDetail.cardType.equals("1")){
					//存折
					bodyEl.addElement("ACCOUNT_TYPE").setText("01");
				}
				else if(p_req1908.singleDetail.cardType.equals("3")){
					//信用卡
					bodyEl.addElement("ACCOUNT_TYPE").setText("02");
				}
				else {//银行卡
					bodyEl.addElement("ACCOUNT_TYPE").setText("00");
				}
				
				//62 开头
				bodyEl.addElement("ACCOUNT_NO").setText(p_req1908.singleDetail.payAct);
				bodyEl.addElement("ACCOUNT_NAME").setText(p_req1908.singleDetail.payName);
				bodyEl.addElement("BANK_NAME").setText(p_req1908.singleDetail.payBankLocation);
				//开户行号 与 清算行号 全部一致
				String[] findValues = new String[2];
				findValues[0] = p_req1908.singleDetail.payBankCode;
				findValues[1] = p_req1908.singleDetail.payAreaName;
				HashMap<String, String> BANK_CODE = this.getBankConfig().getMapAdvanceValues("BankCodeMapping",
						new String[] { "ATSBankCode", "ATSAreaName" }, new String[] { "value" }, findValues);
				if (BANK_CODE != null && BANK_CODE.size() > 0 && BANK_CODE.containsKey("value")) {
					bodyEl.addElement("BANK_CODE").setText(BANK_CODE.get("value"));
					bodyEl.addElement("DRCT_BANK_CODE").setText(BANK_CODE.get("value"));
				}
				else{
					bodyEl.addElement("BANK_CODE").setText("403558000044");
					bodyEl.addElement("DRCT_BANK_CODE").setText("403558000044");
					}
				//保证唯一即可
				bodyEl.addElement("PROTOCOL_NO").setText(""+System.currentTimeMillis());
				bodyEl.addElement("CURRENCY").setText(convertCurToBank(p_req1908.singleDetail.payCur));
				bodyEl.addElement("AMOUNT").setText(StringHelper.amountMultiply100(p_req1908.singleDetail.payAmount));//单位：分
				bodyEl.addElement("ID_TYPE").setText(convertCertTypeToBank(p_req1908.singleDetail.certType));
				bodyEl.addElement("ID").setText(p_req1908.singleDetail.certNum);
				bodyEl.addElement("SUMMARY").setText(p_req1908.singleDetail.purpose);
				bodyEl.addElement("POSTSCRIPT").setText(p_req1908.singleDetail.purpose);
				String xml = Util.formatXml_UTF8(doc);
				this.WriteBankLogLn("发送请求报文："+xml);
				// 签名
				CjSignHelper singHelper = new CjSignHelper(actItem);
				String signMsg = singHelper.signXml$Add(xml);
				
				HttpClient client = new HttpClient();
				client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
				client.getParams().setSoTimeout(10 * 60 * 1000);

				URL url = new URL(bankFront.serverURL);
				String urlstr = url.toString();
				HttpPostBodyMethod post = new HttpPostBodyMethod(urlstr, signMsg);

				int statusCode = client.executeMethod(post);
				if (statusCode != HttpStatus.SC_OK) {
					String err = "访问失败！！HTTP_STATUS=" + statusCode;
					
					System.out.println("返回内容为：" + post.getResponseBodyAsString());
					throw new HttpException(err);
				}//if

				String cjRespmsg = post.getResponseBodyAsString();
				System.out.println(cjRespmsg);
				// 验证签名
				VerifyResult verifyResult = singHelper.verifyCjServerXml(cjRespmsg);
				if (!verifyResult.result) {
					throw new Exception("验证CJ返回数据的签名失败！" + verifyResult.errMsg);
				}
				this.WriteBankLogLn("返回报文："+cjRespmsg);
				StringBuilder tmpSbMsg = new StringBuilder();
				XmlTextReader tmpBkReader = loadBankRespXmlReader(cjRespmsg, tmpSbMsg);
				if(tmpBkReader!=null){
					retDetail.respCode = "0";
					String REQ_SN = tmpBkReader.getFirstText("/MESSAGE/INFO/REQ_SN");
					String ERR_MSG = tmpBkReader.getFirstText("/MESSAGE/INFO/ERR_MSG");
					//String SIGNED_MSG = tmpBkReader.getFirstText("/MESSAGE/INFO/SIGNED_MSG");
					String RET_CODE = tmpBkReader.getFirstText("/MESSAGE/INFO/RET_CODE");
					if(verifyResult.result){
						retDetail.respInfo = "验签成功"+ERR_MSG;
					}
					else {
						retDetail.respInfo = "验签失败"+ERR_MSG;
					}
					retDetail.reqSeqID = REQ_SN;
					retDetail.transState = RET_CODE;
				}
				else{
					retDetail.respCode = "-1";
					retDetail.respInfo = cjRespmsg;
				}
				
			} catch (Exception e) {
				retDetail.respCode = "-1";
				retDetail.respInfo = e.toString();
				e.printStackTrace();
			}		
			return retDetail;
			
		}
	@Override
	public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944)
			throws Exception {
		RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
		RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
		try {
		ActSetItem actItem = getBankConfig().getActSetItem(p_req1944.payAct, "");
		if (actItem == null || !FileHelper.existFile(actItem.ownKeyStorePath)
				|| !FileHelper.existFile(actItem.oppCertFilePath)) {
			if (actItem == null) {
				throw new Exception("未找到账号" + p_req1944.recAct + "的批量商户配置节点");
			} else {
				throw new Exception("账号" + p_req1944.recAct + "的证书文件不存在");
			}
		}
		Document doc = DocumentHelper.createDocument();
		Element msgEl = doc.addElement("MESSAGE");

		Element infoEl = msgEl.addElement("INFO");
		infoEl.addElement("TRX_CODE").setText("G20001");
		infoEl.addElement("VERSION").setText("01");
		infoEl.addElement("MERCHANT_ID").setText(actItem.merchantId);
		infoEl.addElement("REQ_SN").setText(p_req1944.reqHeader.transSeqID);
		infoEl.addElement("TIMESTAMP").setText(U.getCurrentTimestamp());
		infoEl.addElement("SIGNED_MSG").setText("");

		Element bodyEl = msgEl.addElement("BODY");
		bodyEl.addElement("QRY_REQ_SN").setText(p_req1944.askNumber);

		String cjReqmsg = Util.formatXml_UTF8(doc);
		this.WriteBankLogLn("发送请求报文："+cjReqmsg);
		System.out.println("发送请求报文："+cjReqmsg);
		// 签名
		CjSignHelper singHelper = new CjSignHelper(actItem);
		String signMsg = singHelper.signXml$Add(cjReqmsg);
		HttpClient client = new HttpClient();
		client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
		client.getParams().setSoTimeout(10 * 60 * 1000);

		URL url = new URL(bankFront.serverURL);
		String urlstr = url.toString();
		HttpPostBodyMethod post = new HttpPostBodyMethod(urlstr, signMsg);

		int statusCode = client.executeMethod(post);
		if (statusCode != HttpStatus.SC_OK) {
			String err = "访问失败！！HTTP_STATUS=" + statusCode;
			
			System.out.println("返回内容为：" + post.getResponseBodyAsString());
			throw new HttpException(err);
		}//if

		String cjRespmsg = post.getResponseBodyAsString();
		System.out.println(cjRespmsg);
		// 验证签名
		VerifyResult verifyResult = singHelper.verifyCjServerXml(cjRespmsg);
		if (!verifyResult.result) {
			throw new Exception("验证CJ返回数据的签名失败！" + verifyResult.errMsg);
		}
		this.WriteBankLogLn("返回报文："+cjRespmsg);
		System.out.println("返回报文："+cjRespmsg);
		
		StringBuilder tmpSbMsg = new StringBuilder();
		XmlTextReader tmpBkReader = loadBankRespXmlReader(cjRespmsg, tmpSbMsg);
		if(tmpBkReader!=null){
			tmpRetDetail.respCode = "0";
			
			String REQ_SN = tmpBkReader.getFirstText("/MESSAGE/INFO/REQ_SN");//流水号
			
			double secsPasted = DateHelper.getDifferSecs(new Date(), p_req1944.getBgnDateTime());
			double needSecs = 8;
			double waitSecs = needSecs - secsPasted;
				if (waitSecs > 0) {
					tmpRetDetail.respCode = "-1";
					tmpRetDetail.respInfo = "请过5-8秒后再查询（畅捷要求）";
				} else {
					
					String RET_CODE1 = tmpBkReader.getFirstText("/MESSAGE/INFO/RET_CODE");
					if(RET_CODE1.equals("0000")){
						//报头成功
					if(cjRespmsg.indexOf("BODY")>0){
						//有详细信息
						String RET_CODE2 = tmpBkReader.getFirstText("/MESSAGE/BODY/RET_CODE");
						String Amount = tmpBkReader.getFirstText("/MESSAGE/BODY/CHARGE");//交易金额
						String ERR_MSG = tmpBkReader.getFirstText("/MESSAGE/BODY/ERR_MSG");//返回状态信息
						tmpRetDetail.respCode = "0";
						tmpRetDetail.reqSeqID = REQ_SN;//p_req9144.askNumber
						tmpRetDetail.transState = RET_CODE1+"+"+RET_CODE2;
						tmpRetDetail.payInfoCode = RET_CODE1+"+"+RET_CODE2;
						tmpRetDetail.transAmt =StringHelper.amountDivide100( Amount);
						tmpRetDetail.respInfo = ERR_MSG;
					}
					else{
						String RET_CODE = tmpBkReader.getFirstText("/MESSAGE/INFO/RET_CODE");
						String ERR_MSG = tmpBkReader.getFirstText("/MESSAGE/INFO/ERR_MSG");//返回状态信息
						tmpRetDetail.respCode="0";
						tmpRetDetail.reqSeqID= REQ_SN;
						tmpRetDetail.transState = RET_CODE;
						tmpRetDetail.respInfo = ERR_MSG;
					}
					}
					else if(RET_CODE1.equals("2009")){
						//交易不存在
						String ERR_MSG = tmpBkReader.getFirstText("/MESSAGE/INFO/ERR_MSG");//返回状态信息
						tmpRetDetail.respCode = "-1";
						tmpRetDetail.respInfo = ERR_MSG;
					}
					else{
						String ERR_MSG = tmpBkReader.getFirstText("/MESSAGE/INFO/ERR_MSG");
						String RET_CODE = tmpBkReader.getFirstText("/MESSAGE/INFO/RET_CODE");
						tmpRetDetail.respCode = "-1";
						tmpRetDetail.respInfo = ERR_MSG;
						tmpRetDetail.transState = RET_CODE;
					}
				}
		}
		else{
			tmpRetDetail.respCode = "-1";
			tmpRetDetail.respInfo = cjRespmsg;
		}
		
		} catch (Exception e) {
			tmpRetDetail.respCode = "-1";
			tmpRetDetail.respInfo = e.getMessage();
			e.printStackTrace();
		}
		retAts.writeRetDetail(tmpRetDetail);
		return retAts;
	}

	@Override
	public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
		return null;
	}

}
